home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Visual Cafe 3
/
Visual Cafe 3.ISO
/
Vcafe
/
JFC.bin
/
AbstractOptionPaneUI.java
< prev
next >
Wrap
Text File
|
1998-06-30
|
20KB
|
631 lines
/*
* @(#)AbstractOptionPaneUI.java 1.19 98/02/05
*
* Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
*/
package com.sun.java.swing.plaf.basic;
import com.sun.java.swing.*;
import com.sun.java.swing.plaf.*;
import com.sun.java.swing.event.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.Serializable;
/**
* AbstractMessagePaneUI provides a means to place an icon, message and
* buttons into a Container. The layout will look like:<p>
* <pre>
* ------------------
* | i | message |
* | c | message |
* | o | message |
* | n | message |
* ------------------
* | buttons |
* |________________|
* </pre>
* icon is an instance of Icon that is wraped inside a JLabel.
* The message is an opaque object and is tested for the following:
* if the message is a Component it is added to the Container, if
* it is an Icon it is wrapped inside a JLabel and added to the
* Container otherwise it is wrapped inside a JLabel.
* <p>
* The Container, message, icon, and buttons are all determined from
* abstract methods.
* <p>
* Warning: serialized objects of this class will not be compatible with
* future swing releases. The current serialization support is appropriate
* for short term storage or RMI between Swing1.0 applications. It will
* not be possible to load serialized Swing1.0 objects with future releases
* of Swing. The JDK1.2 release of Swing will be the compatibility
* baseline for the serialized form of Swing objects.
*
* @version 1.19 02/05/98
* @author James Gosling
* @author Scott Violet
*/
abstract public class AbstractOptionPaneUI extends OptionPaneUI implements Serializable
{
/** Component to receive focus when messaged with selectInitialValue. */
protected Component initialFocusComponent;
/** This is set to true in validateComponent if a Component is contained
* in either the message or the buttons. */
protected boolean hasCustomComponents;
/**
* Icon to display, null implies no Icon.
*/
abstract public Icon getIcon();
/**
* Returns the message to display.
*/
abstract public Object getMessage();
/**
* Returns the buttons to display.
*/
abstract public Object[] getButtons();
/**
* Returns the Container to place all the Components in.
*/
abstract public Container getContainer();
/**
* Returns the initial index into buttons to select.
*/
abstract public int getInitialIndex();
protected Color getLabelColor() { return UIManager.getColor( "OptionPane.foreground" ); }
/**
* Returns false. This is queried to determine if the buttons should
* be sized to the same width.
*/
public boolean getSizeButtonsToSameWidth() {
return false;
}
/**
* Returns true if in the last call to validateComponent the message
* or buttons contained a subclass of Component.
*/
public boolean containsCustomComponents() {
return hasCustomComponents;
}
/**
* Returns the maximum number of characters to place on a line.
* Default is to return Integer.MAX_VALUE. Concrete implementations
* may want to return a value that means something.
*/
public int getMaxCharactersPerLineCount() {
return Integer.MAX_VALUE;
}
/**
* Requests focus on the initial value.
*/
public void selectInitialValue() {
if (initialFocusComponent != null)
initialFocusComponent.requestFocus();
if (initialFocusComponent instanceof JButton) {
JRootPane root = SwingUtilities.getRootPane(initialFocusComponent);
if (root != null) {
root.setDefaultButton((JButton)initialFocusComponent);
}
}
}
/**
* Recursively creates new JLabel instances to represent <code>d</code>.
* Each JLabel instance is added to <code>c</code>.
*/
protected void burstStringInto(Container c, String d, int maxll) {
// Primitive line wrapping
int len = d.length();
if (len <= 0)
return;
if (len > maxll) {
int p = d.lastIndexOf(' ', maxll);
if (p <= 0)
p = d.indexOf(' ', maxll);
if (p > 0 && p < len) {
burstStringInto(c, d.substring(0, p), maxll);
burstStringInto(c, d.substring(p + 1), maxll);
return;
}
}
c.add(new JLabel(d, JLabel.LEFT));
}
/**
* Creates the appropriate object to represent <code>d</code> and
* places it into <code>container</code>. If <code>d</code> is an
* instance of Component, it is added directly, if it is an Icon,
* a JLabel is created to represent it, otherwise a JLabel is
* created for the string, if <code>d</code> is an Object[], this
* method will be recursively invoked for the children.
* <code>internallyCreated</code> is true if Objc is an instance
* of Component and was created internally by this method (this is
* used to correctly set hasCustomComponents only if !internallyCreated).
*/
protected void appendDescription(Container container,
GridBagConstraints cons,
Object d, int maxll,
boolean internallyCreated) {
if (d == null)
return;
if (d instanceof Component) {
cons.fill = GridBagConstraints.HORIZONTAL;
cons.weightx = 1;
container.add((Component) d, cons);
cons.weightx = 0;
cons.fill = GridBagConstraints.NONE;
cons.gridy++;
if(!internallyCreated)
hasCustomComponents = true;
} else if (d instanceof Object[]) {
Object [] da = (Object[]) d;
for (int i = 0; i < da.length; i++)
appendDescription(container, cons, da[i], maxll, false);
} else if (d instanceof Icon) {
JLabel label = new JLabel( (Icon)d, maxll );
label.setForeground( getLabelColor() );
appendDescription(container, cons, label, maxll, true);
} else {
String s = d.toString();
int len = s.length();
if (len <= 0)
return;
int nl = s.indexOf('\n');
if (nl >= 0) {
// break up newlines
if(nl == 0)
appendDescription(container, cons, new Component() {
public Dimension getPreferredSize() {
Font f = getFont();
if(f != null)
return new Dimension(1, f.getSize() + 2);
return new Dimension(0, 0);
}
}, maxll, true);
else
appendDescription(container, cons, s.substring(0, nl),
maxll, false);
appendDescription(container, cons, s.substring(nl + 1), maxll,
false);
} else if (len > maxll) {
Container c = Box.createVerticalBox();
burstStringInto(c, s, maxll);
appendDescription(container, cons, c, maxll, true );
} else {
JLabel label = new JLabel( s, JLabel.LEFT );
label.setForeground( getLabelColor() );
appendDescription(container, cons, label, maxll, true);
}
}
}
/**
* Creates the appropriate object to represent each of the objects in
* <code>buttons</code> and adds it to <code>container</code>. This
* differs from appendDescription in that it will recurse on
* <code>buttons</code> and that if button is not a Component
* it will create an instance of JButton, that when pressed will
* invoke <code>createdButtonFired</code> with the appropriate
* index.
*/
protected void appendButtons(Container container, Object[] buttons,
int initialIndex) {
if(buttons != null && buttons.length > 0) {
boolean sizeButtonsToSame = getSizeButtonsToSameWidth();
boolean createdAll = true;
int numButtons = buttons.length;
JButton[] createdButtons = null;
int maxWidth = 0;
if(sizeButtonsToSame)
createdButtons = new JButton[numButtons];
for(int counter = 0; counter < numButtons; counter++) {
Object anO = buttons[counter];
Component newComponent;
if(anO instanceof Component) {
createdAll = false;
newComponent = (Component)anO;
container.add(newComponent);
hasCustomComponents = true;
}
else {
JButton aButton;
if(anO instanceof Icon)
aButton = new JButton((Icon)anO);
else
aButton = new JButton(anO.toString());
container.add(aButton);
final int buttonIndex = counter;
aButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
createdButtonFired(buttonIndex);
}
});
newComponent = aButton;
}
if(sizeButtonsToSame && createdAll &&
(newComponent instanceof JButton)) {
createdButtons[counter] = (JButton)newComponent;
maxWidth = Math.max(maxWidth,
newComponent.getMinimumSize().width);
}
if(counter == initialIndex) {
initialFocusComponent = newComponent;
if (initialFocusComponent instanceof JButton) {
JButton defaultB = (JButton)initialFocusComponent;
defaultB.addAncestorListener(new AncestorListener() {
public void ancestorAdded(AncestorEvent e) {
JButton defaultButton = (JButton)e.getComponent();
JRootPane root = SwingUtilities.getRootPane(defaultButton);
if (root != null) {
root.setDefaultButton(defaultButton);
}
}
public void ancestorRemoved(AncestorEvent event) {}
public void ancestorMoved(AncestorEvent event) {}
});
}
}
}
((SyncingLayoutManager)container.getLayout()).
setSyncsAll((sizeButtonsToSame && createdAll));
/* Set the padding, windows seems to use 8 if <= 2 components,
otherwise 4 is used. It may actually just be the size of the
buttons is always the same, not sure. */
if(sizeButtonsToSame && createdAll) {
JButton aButton;
int padSize;
if(numButtons <= 2)
padSize = 8;
else
padSize = 4;
for(int counter = 0; counter < numButtons; counter++) {
aButton = createdButtons[counter];
aButton.setMargin(new Insets(2, padSize, 2, padSize));
}
}
}
}
/**
* Invoked when a button that was created in <code>appendButtons</code>
* has been pressed. <code>buttonIndex</code> identifies the index
* of the button from the <code>buttons</code>array that was passed
* into <code>appendButtons</code>.
*/
public void createdButtonFired(int buttonIndex) {
}
/**
* Messaged from <code>validateComponent</code> to remove all the
* components from <code>container</code>. This invokes removeAll
* on <code>container</code>, but is provided should subclasses wish
* to not remove everything.
*/
protected void emptyContainer(Container container) {
container.removeAll();
}
/**
* Creates and adds a JLabel representing the icon returned from
* <code>getIcon</code> to <code>top</code>. This is messaged from
* <code>createBody</code>
*/
protected void addIcon(Container top) {
/* Create the icon. */
Icon sideIcon = getIcon();
if (sideIcon != null) {
JLabel iconLabel = new JLabel(sideIcon);
iconLabel.setVerticalAlignment(SwingConstants.TOP);
top.add(iconLabel, BorderLayout.WEST);
}
}
/**
* Messaged from validateComponent to create a Container containing the
* body of the message. The icon is the created by calling
* <code>addIcon</code>.
*/
protected Container createBody() {
Container top = new Container() {
public Insets getInsets() {
return getBodyInsets();
}
};
top.setLayout(new BorderLayout());
/* Fill the body. */
GridBagConstraints cons = new GridBagConstraints();
Container body = new Container() {};
Container realBody = new Container() {};
realBody.setLayout(new BorderLayout());
realBody.add(new Container() {
public Dimension getPreferredSize() {
return new Dimension(15, 1);
}
}, BorderLayout.WEST);
realBody.add(body, BorderLayout.CENTER);
body.setLayout(new GridBagLayout());
cons.gridx = cons.gridy = 0;
cons.gridwidth = GridBagConstraints.REMAINDER;
cons.gridheight = 1;
cons.anchor = GridBagConstraints.WEST;
cons.insets = new Insets(0,0,3,0);
appendDescription(body, cons, getMessage(),
getMaxCharactersPerLineCount(), false);
top.add(realBody, BorderLayout.CENTER);
addIcon(top);
return top;
}
/**
* Returns the insets to be used in the Container housing the buttons.
*/
protected Insets getButtonInsets() {
return new Insets(6, 0, 0, 0);
}
/**
* Returns the insets to be used for the body, the body contains both
* the image and the actual message.
*/
protected Insets getBodyInsets() {
return new Insets(0, 0, 0, 0);
}
/**
* Creates and returns a Container containin the buttons. The buttons
* are created by calling <code>getButtons</code>.
*/
protected Container createButtons() {
/* And the bottom for all the buttons. */
Container bottom = new Container() {
public Insets getInsets() {
return getButtonInsets();
}
};
bottom.setLayout(new SyncingLayoutManager(true, 6));
appendButtons(bottom, getButtons(), getInitialIndex());
return bottom;
}
/**
* Removes all the components from the Container, adds the icon,
* message and buttons.
*/
protected void validateComponent() {
Container container = getContainer();
hasCustomComponents = false;
initialFocusComponent = null;
if(container != null) {
emptyContainer(container);
container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
container.add(createBody());
container.add(createButtons());
}
}
/**
* SyncingLayoutManager acts similiar to FlowLayout. It lays out all
* components from left to right. If syncsAll is true, the widths
* of each component will be set to the largest preferred size width.
*/
public static class SyncingLayoutManager implements LayoutManager,
Serializable {
protected boolean syncsAll;
protected int padding;
/** If true, children are lumped together in parent. */
protected boolean centersChildren;
public SyncingLayoutManager(boolean syncsAll, int padding) {
this.syncsAll = syncsAll;
this.padding = padding;
centersChildren = true;
}
public void setSyncsAll(boolean newValue) {
syncsAll = newValue;
}
public boolean getSyncsAll() {
return syncsAll;
}
public void setPadding(int newPadding) {
this.padding = newPadding;
}
public int getPadding() {
return padding;
}
public void setCentersChildren(boolean newValue) {
centersChildren = newValue;
}
public boolean getCentersChildren() {
return centersChildren;
}
public void addLayoutComponent(String string, Component comp) {
}
public void layoutContainer(Container container) {
Component[] children = container.getComponents();
if(children != null && children.length > 0) {
int numChildren = children.length;
Dimension[] sizes = new Dimension[numChildren];
int counter;
int yLocation = container.getInsets().top;
if(syncsAll) {
int maxWidth = 0;
for(counter = 0; counter < numChildren; counter++) {
sizes[counter] = children[counter].getPreferredSize();
maxWidth = Math.max(maxWidth, sizes[counter].width);
}
int xLocation;
int xOffset;
if(getCentersChildren()) {
xLocation = (container.getSize().width -
(maxWidth * numChildren +
(numChildren - 1) * padding)) / 2;
xOffset = padding + maxWidth;
}
else {
if(numChildren > 1) {
xLocation = 0;
xOffset = (container.getSize().width -
(maxWidth * numChildren)) /
(numChildren - 1) + maxWidth;
}
else {
xLocation = (container.getSize().width -
maxWidth) / 2;
xOffset = 0;
}
}
for(counter = 0; counter < numChildren; counter++) {
children[counter].setBounds(xLocation, yLocation,
maxWidth,
sizes[counter].height);
xLocation += xOffset;
}
}
else {
int totalWidth = 0;
for(counter = 0; counter < numChildren; counter++) {
sizes[counter] = children[counter].getPreferredSize();
totalWidth += sizes[counter].width;
}
totalWidth += ((numChildren - 1) * padding);
boolean cc = getCentersChildren();
int xOffset;
int xLocation;
if(cc) {
xLocation = (container.getSize().width -
totalWidth) / 2;
xOffset = padding;
}
else {
if(numChildren > 1) {
xOffset = (container.getSize().width -
totalWidth) / (numChildren - 1);
xLocation = 0;
}
else {
xLocation = (container.getSize().width -
totalWidth) / 2;
xOffset = 0;
}
}
for(counter = 0; counter < numChildren; counter++) {
children[counter].setBounds(xLocation, yLocation,
sizes[counter].width, sizes[counter].height);
xLocation += xOffset + sizes[counter].width;
}
}
}
}
public Dimension minimumLayoutSize(Container c) {
if(c != null) {
Component[] children = c.getComponents();
if(children != null && children.length > 0) {
Dimension aSize;
int numChildren = children.length;
int height = 0;
Insets cInsets = c.getInsets();
int extraHeight = cInsets.top + cInsets.bottom;
if(syncsAll) {
int maxWidth = 0;
for(int counter = 0; counter < numChildren; counter++){
aSize = children[counter].getPreferredSize();
height = Math.max(height, aSize.height);
maxWidth = Math.max(maxWidth, aSize.width);
}
return new Dimension(maxWidth * numChildren +
(numChildren - 1) * padding,
extraHeight + height);
}
else {
int totalWidth = 0;
for(int counter = 0; counter < numChildren; counter++){
aSize = children[counter].getPreferredSize();
height = Math.max(height, aSize.height);
totalWidth += aSize.width;
}
totalWidth += ((numChildren - 1) * padding);
return new Dimension(totalWidth, extraHeight + height);
}
}
}
return new Dimension(0, 0);
}
public Dimension preferredLayoutSize(Container c) {
return minimumLayoutSize(c);
}
public void removeLayoutComponent(Component c) { }
}
}